﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using HostServicePhoneCommands.AppConfig;
using HostServicePhoneCommands.Properties;
using InterfacesPhoneCommands;

namespace HostServicePhoneCommands
{
    static class Program
    {
        internal static LoadedAssemblies AssembliesLoaded = new LoadedAssemblies();
        internal static IPhoneService PhoneService;
        internal static bool DebugMode;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            var aProcess = Process.GetCurrentProcess();
            var aProcName = aProcess.ProcessName;
            if (Process.GetProcessesByName(aProcName).Length > 1)
            {
                MessageBox.Show(Resources.AlreadyRunning, Resources.NameApp, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (args.Length > 0 && args[0].Equals("Debug"))
                DebugMode = true;

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //load wcf host and services
            LoadServicesFromSettings();
            if (AssembliesLoaded.LoadAssemblyError.Any())
            {
                foreach (var errors in AssembliesLoaded.LoadAssemblyError)
                {
                    var msgerr = errors.Error;
                    if (errors.InnerException != null)
                    {
                        msgerr += " InnerException: " + errors.InnerException.Message;
                    }
                    MessageBox.Show(string.Format(Resources.MsgServiceFailed, Resources.Service, errors.Alias, msgerr), Resources.NameApp, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return;
            }
            Application.Run(new SysTrayApp());
        }

        internal static void LoadServicesFromSettings()
        {
            var configFile = Assembly.GetExecutingAssembly().Location + ".config";
            foreach (var serviceSetting in GetCustomConfigSection.GetServiceSettings<List<ServiceSetting>>(configFile, "serviceSettings").Where(serviceSetting => serviceSetting.Enabled))
            {
                var directoryName = (new FileInfo(configFile)).DirectoryName;
                if (directoryName != null)
                {
                    var currentAssembly = Path.Combine(directoryName, serviceSetting.Assembly);
                    if (File.Exists(currentAssembly))
                    {
                        var classType = Assembly.LoadFrom(currentAssembly).GetType(serviceSetting.ClassName);

                        if (classType != null)
                        {
                            var iClass = classType.GetInterface("IService");
                            if (iClass != null)
                            {
                                var service = (IService)Activator.CreateInstance(classType, true);
                                try
                                {
                                    service.InitService();
                                    AssembliesLoaded.LoadedServices.Add(
                                        new LoadAssemblyIService
                                            {
                                                Alias = serviceSetting.Alias,
                                                Assembly = serviceSetting.Assembly,
                                                ClassName = serviceSetting.ClassName,
                                                DateRef = DateTime.Now,
                                                Application = Resources.NameApp,
                                                Service = service
                                            });
                                    // ReSharper disable SuspiciousTypeConversion.Global
                                    if (service as IPhoneService != null)
                                    {
                                        PhoneService = (IPhoneService) service;
                                    }
                                    // ReSharper restore SuspiciousTypeConversion.Global
                                }
                                catch (Exception ex)
                                {
                                    AssembliesLoaded.LoadAssemblyError.Add(
                                        new LoadAssemblyError
                                        {
                                            Assembly =serviceSetting.Assembly,
                                            InnerException = ex,
                                            ClassName =serviceSetting.ClassName,
                                            Alias = serviceSetting.Alias,
                                            Application = Resources.NameApp,
                                            DateRef = DateTime.Now
                                        });
                                }
                            }
                            else
                            {
                                AssembliesLoaded.LoadAssemblyError.Add(
                                    new LoadAssemblyError
                                    {
                                        Assembly = serviceSetting.Assembly,
                                        InnerException = new TypeLoadException("IService"),
                                        ClassName = serviceSetting.ClassName,
                                        Alias = serviceSetting.Alias,
                                        Application = Resources.NameApp,
                                        DateRef = DateTime.Now
                                    });
                            }
                        }
                        else
                        {
                            AssembliesLoaded.LoadAssemblyError.Add(
                                new LoadAssemblyError
                                {
                                    Assembly = serviceSetting.Assembly,
                                    InnerException =new TypeLoadException(serviceSetting.ClassName),
                                    ClassName = serviceSetting.ClassName,
                                    Alias = serviceSetting.Alias,
                                    Application = Resources.NameApp,
                                    DateRef = DateTime.Now
                                });
                        }
                    }
                    else
                    {
                        AssembliesLoaded.LoadAssemblyError.Add(
                            new LoadAssemblyError
                            {
                                Assembly = serviceSetting.Assembly,
                                InnerException =
                                    new FileNotFoundException(currentAssembly),
                                ClassName = serviceSetting.ClassName,
                                Alias = serviceSetting.Alias,
                                Application = Resources.NameApp,
                                DateRef = DateTime.Now
                            });
                    }
                }
                else
                {
                    throw new FileNotFoundException(configFile);
                }
            }
        }
    }
}
